package com.example.thread;

import com.example.MyMetaObject.User;
import com.sun.corba.se.spi.legacy.connection.GetEndPointInfoAgainException;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SingleThreadedExcutionPattern {

    public static void main(String[] args){
        System.out.println("Testing Gate.");
        Lock lock = new ReentrantLock();
        Gate gate = new Gate(lock);
        new UserThread(gate,"Alice","Alaska").start();
//        new TestUserThread(gate).start();
        new UserThread(gate,"Bobby","Brazil").start();
//        new TestUserThread(gate).start();
        new UserThread(gate,"Chris","Canada").start();
        new TestUserThread(gate).start();
    }

    static class TestUserThread extends Thread{
        private final Gate gate;
        TestUserThread(Gate gate){
            this.gate = gate;
        }

        @Override
        public void run() {
            while(true){
                System.out.println(gate.toStr());
            }
        }
    }

    static class UserThread extends Thread{
        private final Gate gate;
        private final String myname;
        private final String myaddress;

        UserThread(Gate gate, String myname, String myaddress) {
            this.gate = gate;
            this.myname = myname;
            this.myaddress = myaddress;
        }

        @Override
        public void run() {
            System.out.println(myname + " BEGIN");
            while(true){
                gate.pass(myname,myaddress);
            }
        }
    }


    static class Gate{
        private int counter = 0;
        private String name = "Nobody";
        private String address = "Nowhere";
        private Lock lock;

        Gate(Lock lock){
            this.lock = lock;
        }

        public  void  pass(String name, String address) {
            lock.lock();
            try{
                this.counter++;
                this.name = name;
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                this.address = address;
                //
                check();
            }finally {
                lock.unlock();
            }
        }

        private String toStr(){
            lock.lock();
            String temp = name;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            String str = "No." + counter + ":" + temp + "," + address;
            lock.unlock();
            return str;
        }

        private void  check(){
            if(name.charAt(0) != address.charAt(0)){
                System.out.println("*******BOKEN*****" + toStr());
            }
//            else {
//                System.out.println("TTTT"+toStr());
//            }
        }
    }
}
